package com.gemframework.common.interceptor;


import com.gemframework.common.annotation.ApiAuth;
import com.gemframework.common.exception.ApiException;
import com.gemframework.common.util.JwtUtil;
import com.gemframework.common.util.MapDataUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * API权限验证
 */
@Component
public class ApiInterceptor extends HandlerInterceptorAdapter {
    private Logger logger = LoggerFactory.getLogger(getClass());

    public static final String API_PATH = "api";//API路径名
    private static final String signSecret = "afeng2020";//签名盐值
    private static final String signHeaderKey = "sign";//签名请求头key


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod;
        if (handler instanceof HandlerMethod) {
            handlerMethod = (HandlerMethod) handler;
        } else {
            return true;
        }
        // 获取方法上的注解
        ApiAuth apiAuth = handlerMethod.getMethodAnnotation(ApiAuth.class);
        if (apiAuth == null) {
            // 如果方法上的注解为空 则获取类的注解
            apiAuth = handlerMethod.getMethod().getDeclaringClass().getAnnotation(ApiAuth.class);
        }
        if (apiAuth != null) {
            //验证签名
            if (apiAuth.isAuthSign()) {
                if (!verifySign(request, response)) {
                    throw new ApiException("签名验证失败：API非法请求");
                }
            }
            //验证登录token
            if (apiAuth.isAuthLogin()) {
                verifyLogin(request, response);
            }
        }

        return true;
    }

    /**
     * Description: 验证参数签名
     *
     * @author afeng
     * @date 2020/1/19 22:39
     */
    private boolean verifySign(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, Object> paramsMap = MapDataUtil.convertDataMap(request);
        Set<String> keySet = paramsMap.keySet();
        //所有请求参数排序后键值对拼接
        List<String> paramNames = new ArrayList<>(keySet);
        Collections.sort(paramNames);
        StringBuilder paramNameValue = new StringBuilder();
        for (String paramName : paramNames) {
            paramNameValue.append(paramName).append(paramsMap.get(paramName));
        }
        String source = signSecret + paramNameValue.toString() + signSecret;
        String signAuth = DigestUtils.md5Hex(source).toUpperCase();
        logger.debug("signAuth = " + signAuth);
        return StringUtils.equals(signAuth, request.getHeader(signHeaderKey));
    }

    /**
     * 登录验证
     *
     * @author afeng
     */
    private void verifyLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //从header中获取token
        String token = JwtUtil.getToken();
        //token为空
        if (StringUtils.isBlank(token)) {
            throw new ApiException("token不能为空");
        }
        //查询token信息
        String userId = JwtUtil.queryByToken(token);
        if (StringUtils.isBlank(userId)) {
            throw new ApiException("token解密失败");
        }
        if (!JwtUtil.verifyToken(token, userId)) {
            throw new ApiException("token失效，请重新登录");
        }
        //刷新token
        String refreshToken = JwtUtil.createToken(userId);
        //设置token到响应头由前端获取
        response.setHeader("Authorization", refreshToken);
    }
}
